package server

import (
	"fmt"
	"sync"
)

type OpState uint8

const (
	OP_NONE    OpState = 0x00
	OP_INSTALL OpState = 0x01
	OP_START   OpState = 0x02
	OP_STOP    OpState = 0x04
	OP_CLEAN   OpState = 0x08
	OP_MASK    OpState = OP_INSTALL | OP_START | OP_STOP | OP_CLEAN
)

var (
	// Key: server_type + ":" + server_port
	// example: "redis_cluster:6400", "redis:6700"
	KeyOpMap map[string]*KeyOp = make(map[string]*KeyOp)
)

type KeyOp struct {
	Key string

	opState OpState
	mu      sync.Mutex
}

func NewKeyOp(key string) *KeyOp {
	return &KeyOp{Key: key, opState: OP_NONE}
}

func (o *KeyOp) State() OpState {
	o.mu.Lock()
	defer o.mu.Unlock()
	return o.state()
}

func (o *KeyOp) state() OpState {
	return o.opState & OP_MASK
}

func (o *KeyOp) Clear() OpState {
	o.mu.Lock()
	defer o.mu.Unlock()
	// 比较暴力设置为OP_NONE
	// 只适用于各个状态是两两互斥的前提下
	return o.clear()
}
func (o *KeyOp) clear() OpState {
	o.opState = OP_NONE
	return o.opState
}

func (o *KeyOp) SetState(target OpState) (OpState, error) {
	o.mu.Lock()
	defer o.mu.Unlock()
	curState := o.state()
	// 先验证
	if curState != OP_NONE {
		// 如已设置状态，则错误返回
		return OP_NONE, fmt.Errorf("already setup state: %x", curState)
	}
	switch target {
	case OP_NONE:
		// 相当于 clear 状态
		return o.clear(), nil
	case OP_INSTALL, OP_START, OP_STOP, OP_CLEAN:
		o.opState = target
		return o.state(), nil
	default:
		return OP_NONE, fmt.Errorf("bad OpState argu: %x", target)
	}
}
